// 继承与实例化 共同点 抽象->具象
// 狭义的继承 发生在 类与类之间 实例化是类与对象之间
// js原生不支持继承和实例化 内在是用原型链去实现继承和实例化的
// 水果 父类 -》 苹果 子类-》 三斤的苹果 两斤的苹果 实例化后的对象
// 子类继承父类 一般是造成属性或方法数量上的增加
// 类实例化对象 不会造成属性或方法数量上增加，而是赋值内容不同。
class Shape {
  name;
  constructor(name) {
    console.log("初始化图形", name);
    this.name = name;
  }
  calcSquare() {
    console.log("=======原始图形=======", this.name);
    return 100;
  }
}

// 子类 继承于 父类 能够自动获取 父类的非私有的属性和方法
// 子类需要在构造函数中需要调用super()方法 交代参数
// 子类 可以重写父类里面的同名方法 称为override 覆写方法
// 子类 可以自由的额外添加其他属性和方法。
class Rect extends Shape {
  //   对象的属性
  a = 3;
  b = 5;
  //   构造函数/方法
  constructor(a, b) {
    super(`这是一个长${a}宽${b}的长方形`);
    //   new Shape(`这是一个长${a}宽${b}的长方形`)
    this.a = a;
    this.b = b;
  }
  //   对象的方法/函数
  calcSquare() {
    console.log(this.name);
    return this.a * this.b;
  }
  calcZhouchang() {
    return 2 * (this.a + this.b);
  }
}
// class Circle extends Shape {
//   r = 1;
//   constructor(r) {
//     super("t");
//     this.r = r;
//   }
//   calcSquare() {
//     return this.r ** 2;
//   }
// }

function test01() {
  let s = new Shape("空洞图形");
  console.log(s.calcSquare());
  console.log(s);
  let t = new Rect(10, 22);
  console.log(t.calcSquare());
  console.log(t);
}

class Circle extends Shape {
  r = 10;

  constructor(label, r) {
    super(label);
    this.r = r;
  }
  calcSquare() {
    // 调用父类方法calcSquare
    super.calcSquare();
    return this.r ** 2 * Math.PI;
  }
}

function test02() {
  let c = new Circle("这是一个圆型", 10);
  console.log(c);
  console.log(c.calcSquare());
}
//   Object 是一切js引用类型的父类
//  Array Function 是直接继承Object的子类 Date
//  引用类型中 使用 obj instanceof ClassName 判断类型
// 写 类 =》 累
class Person {
  name;
  partner;
  constructor(name) {
    this.name = name;
  }
  show() {
    // console.log(this.name,this.partner)
    // console.log(this);
    console.log(JSON.stringify(this));
  }
}
function test03() {
  let z = new Person("zhangsan");
  let l = new Person("lisi");
  // z.partner = l;
  l.partner = z;
  z.show();
  l.show();
}

class Printer {
  // n;
  // callback;
  // constructor(n = 9,callback) {
  //   this.n = n;
  //   this.callback = callback;
  // }
  defaultConfig = {
    n: 9,
    callback: () => {
      console.log("**************");
    },
  };
  constructor(userConfig) {
    // this.defaultConfig = userConfig || this.defaultConfig;
    this.defaultConfig = 
    Object.assign(this.defaultConfig,userConfig)
  }
  printerHeader() {
    console.log("N阶乘法表");
  }
  printMulti() {
    this.printerHeader();
    this.defaultConfig.callback();
    // if(this.callback){
    //   this.callback()
    // }
    for (let m = 1; m <= this.defaultConfig.n; m++) {
      let line = "";
      // let a = m;
      for (let i = 1; i <= m; i++) {
        // let b=i;
        let unit = m + "*" + i + "=" + m * i + " ";
        // console.log(unit);
        line = line + unit;
      }
      console.log(line);
    }
  }
}

function test04() {
  // console.log("PPPPPPPPP");
  let printer = new Printer({
    n: 4,
    callback: () => {
      console.log("PPPPPPPPPP");
      console.log("************");
    },
  });
  printer.printMulti();
  let printer2 = new Printer({
    callback: () => {
      console.log("&&&&&&&&&&&");
    },
  });
  printer2.printMulti();
  let printer3 = new Printer({
    n: 6,
  });
  printer3.printMulti();
}

// ===========main========
test01();
test02();
// test03();
// 序列化 就是  对象----字符串 注意不恰当的序列化可能会造成死循环

// test04();
